﻿using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Abp.Application.Services;
using Abp.IdentityFramework;
using Abp.Runtime.Session;
using LZ.DCode.Authorization.Users;
using LZ.DCode.MultiTenancy;
using Abp.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using LZ.DCode.Configuration;
using System.Collections.Generic;
using System.IO;
using NPOI.SS.UserModel;
using System.Reflection;
using NPOI.XSSF.UserModel;

namespace LZ.DCode
{
    /// <summary>
    /// Derive your application services from this class.
    /// </summary>
    public abstract class DCodeAppServiceBase : ApplicationService
    {
        public TenantManager TenantManager { get; set; }

        public UserManager UserManager { get; set; }

        protected DCodeAppServiceBase()
        {
            LocalizationSourceName = DCodeConsts.LocalizationSourceName;
        }

        protected virtual Task<User> GetCurrentUserAsync()
        {
            var user = UserManager.FindByIdAsync(AbpSession.GetUserId().ToString());
            if (user == null)
            {
                throw new Exception("There is no current user!");
            }

            return user;
        }

        protected virtual User GetCurrentUser()
        {
            return AsyncHelper.RunSync(GetCurrentUserAsync);
        }

        protected virtual Task<Tenant> GetCurrentTenantAsync()
        {
            using (CurrentUnitOfWork.SetTenantId(null))
            {
                return TenantManager.GetByIdAsync(AbpSession.GetTenantId());
            }
        }

        protected virtual Tenant GetCurrentTenant()
        {
            using (CurrentUnitOfWork.SetTenantId(null))
            {
                return TenantManager.GetById(AbpSession.GetTenantId());
            }
        }

        protected virtual void CheckErrors(IdentityResult identityResult)
        {
            identityResult.CheckErrors(LocalizationManager);
        }
    }


    public class CommHelper<T>
    {

        private readonly IHostingEnvironment _hostingEnvironment;

        private readonly IConfigurationRoot _appConfiguration;
        public CommHelper(IHostingEnvironment hostingEnvironment)
        {
            this._hostingEnvironment = hostingEnvironment;

            this._appConfiguration = AppConfigurations.Get(hostingEnvironment.ContentRootPath, hostingEnvironment.EnvironmentName, hostingEnvironment.IsDevelopment());
        }

        #region NPOI Excel导出功能 +ExcelOut(List<T> arr, string path, List<string> Attries, List<string > headers)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="arr">实体</param>
        /// <param name="path">导出路径</param>
        /// <param name="Attries">实体的属性</param>
        /// <param name="headers">表头</param>
        public string ExcelOut(List<T> arr, List<string> Attries, List<string> headers)
        {
            string webRootPath = _hostingEnvironment.WebRootPath;
            var uid = Guid.NewGuid().ToString();
            string newFileName = uid + ".xlsx"; //随机生成新的文件名
            var fileDire = webRootPath + "/excel/";
            if (!Directory.Exists(fileDire))
            {
                Directory.CreateDirectory(fileDire);
            }
            var path = fileDire + newFileName;
            try
            {
                IWorkbook workbook = null;//创建一个工作薄
                workbook = new XSSFWorkbook();
                ISheet sheet = workbook.CreateSheet();//在工作薄中创建一个工作表
                IRow rw_head = sheet.CreateRow(0);

                for (int i = 0; i < headers.Count; i++) //循环一个表头来创建第一行的表头
                {
                    rw_head.CreateCell(i).SetCellValue(headers[i]);
                }
                Type t = typeof(T); //获取得泛型集合中的实体， 返回T的类型
                PropertyInfo[] properties = t.GetProperties(); //返回当前获得实体后 实体类型中的所有公共属性
                for (int i = 0; i < arr.Count; i++)//循环实体泛型集合
                {
                    IRow rw = sheet.CreateRow(i + 1);//创建一个新行，把传入集合中的每条数据创建一行
                    foreach (PropertyInfo property in properties)//循环得到的所有属性（想要把里面指定的属性值导出到Excel文件中）
                    {
                        for (int j = 0; j < Attries.Count; j++)//循环需要导出属性值 的 属性名
                        {
                            string attry = Attries[j];//获得一个需要导入的属性名；
                            if (string.Compare(property.Name.ToUpper(), attry.ToUpper()) == 0)//如果需要导出的属性名和当前循环实体的属性名一样，
                            {
                                object result = property.GetValue(arr[i], null);//获取当前循环的实体属性在当前实体对象（arr[i]）的值
                                rw.CreateCell(j).SetCellValue((result == null) ? string.Empty : result.ToString());//创建单元格并进行赋值
                            }
                        }
                    }
                }
                using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    workbook.Write(fs);
                }

                return _appConfiguration["App:ServerRootAddress"] + "excel/" + newFileName;
            }
            catch (Exception ex)
            {

                throw new Exception("在导出Excel时文件出错啦=====" + ex.Message);
            }
        }
        #endregion
    }
}

